Possible Code Changes:

 

If you convert an existing POD member to a pseudoPOD member, most of the code using the existing member will not need changing.  However, no masquerade is perfect, and I have found several cases that require changing the code.

 

1) printf(...) Prodding:

Variadic functions such as printf(...) statements need some compiler helper, i.e. if the pseudoPOD is an argument in a call that can have a variable number of arguments, the compiler needs to be told the type of the member.  The statement:

printf ("value of smart member fred.int1 = %d", (int)fred.int1);

compiles and runs correctly, but remove "(int)" and the compiler produces the error message:

"cannot pass objects of non-POD type 'class fred2_c::int3_nest' through '...'; call will abort at runtime".

C++ I/O streams (e.g.cout << fred.int1;  ) don't have this problem.

 

2) Template Prodding:

Templates sometimes require similar prodding.  For example, the absolute value template used in file main.cpp accompanying this article (www.dlmowery.com/pseudoPOD/main.cpp):

template <class T> T absfloat(T a) {

     if (a<0) {return -a;} else {return a;}

}

attempts to make a copy of argument a, which I've intentionally made impossible for pseudoPODs, so

absfloat( fred.int3 );

will fail if fred.int3 is a pseudoPOD, but work correctly if we use a typecast to prod the compiler into converting the pseudoPOD to a POD, as in

absfloat( (int)fred.int3 );

Some template calls require prodding, and others don't.  For example,

absfloat( fred.int3 - 48 );

does not require changing the code, because the -48 part already persuades the compiler to convert fred.int3 to an integer.

The macro equivalent,

#define absfloat_macro(a) ((a)<0)?-(a):(a);

needs no recoding.

The compiler does not plainly say that it tried to make a copy of the pseudoPOD and was stymied, instead it complains that the copy constructor() or destructor() is private, so it can't use it, e.g.

"'fred2_c::int3_nest::~int3_nest()' is private"

So the keyword "private" is often your cue to prod the compiler by adding a type cast.

 

3) Passing pseudoPOD by Reference:

If you pass a member to a function by reference (rather than by value, which is more common), then using a POD for the argument will succeed, but using a pseudoPOD will fail.  You can often correct the problem, without changing all the places where the function is called, by converting the function to a template, e.g. change function addbyadr() from:

int addbyadr (int &a, int b) { a = a + b; return (a); }

to:

template <class T> int addbyadr (T &a,int b) {a = a + b; return(a);}

and now argument &a can handle both PODs and pseudoPODs.  The template does not require type cast prodding because passing by reference does not make a copy.

 

4) Pointer Variable Type:

If you use pointer variables to point at pseudoPODs you'll have to change the type of the pointer, for example, if a class fred_c contained a pseudoPOD member int1, then you'd have to change

int *int1p;           to        fred_c::int3_c *int1p;